﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace DotNetMigrations.Commands
{
	/// <summary>
	/// Factory used to instantiate console commands
	/// and get command information.
	/// </summary>
	public class ConsoleCommandFactory
	{
		/// <summary>
		/// Get an instance of the specified command
		/// and pass it an array of arguments.
		/// </summary>
		public static ConsoleCommand GetCommand(string commandName, string[] args)
		{
			Assembly a = Assembly.GetExecutingAssembly();
			Type[] types = a.GetTypes();
			foreach (Type t in types)
			{
				if (t.BaseType != typeof(ConsoleCommand))
					continue;

				object[] attrs = t.GetCustomAttributes(typeof(ConsoleCommandAttribute), false);
				if (attrs.GetLength(0) == 0)
					continue;

				ConsoleCommandAttribute cmdAttr = (ConsoleCommandAttribute)attrs[0];
				if (!string.Equals(cmdAttr.CommandName, commandName, StringComparison.CurrentCultureIgnoreCase))
					continue;

				ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string[]) });
				object[] ciArgs = { args };
				ConsoleCommand cmd = (ConsoleCommand)ci.Invoke(ciArgs);

				return cmd;
			}

			return null;
		}

		/// <summary>
		/// Get a list of all the available commands.
		/// </summary>
		private static ConsoleCommandAttribute[] GetAllConsoleCommands()
		{
			List<ConsoleCommandAttribute> commandAttrs = new List<ConsoleCommandAttribute>();

			Assembly a = Assembly.GetExecutingAssembly();
			Type[] types = a.GetTypes();
			foreach (Type t in types)
			{
				if (t.BaseType != typeof(ConsoleCommand))
					continue;

				object[] attrs = t.GetCustomAttributes(typeof(ConsoleCommandAttribute), false);
				if (attrs.GetLength(0) == 0)
					continue;

				ConsoleCommandAttribute cmd = (ConsoleCommandAttribute)attrs[0];
				commandAttrs.Add(cmd);
			}

			return commandAttrs.ToArray();
		}
	}
}
